package com.ihr360.oneclick.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ihr360.commons.request.MailRequest;
import com.ihr360.message.dao.MessageSendRecordDao;
import com.ihr360.message.dao.MessageSendTaskDao;
import com.ihr360.message.dto.MessageSendRecordDto;
import com.ihr360.message.dto.MessageSendTaskDto;
import com.ihr360.message.modal.WxMpProgramTemplateMessage;
import com.ihr360.message.modal.WxMpTemplateData;
import com.ihr360.message.modal.WxMpTemplateMessage;
import com.ihr360.message.service.impl.ExecuteSendTaskService;
import com.ihr360.oneclick.config.SmsConfig;
import com.ihr360.oneclick.dao.CompanyFreeMessageDao;
import com.ihr360.oneclick.dao.SpreadsheetRowDao;
import com.ihr360.oneclick.dto.CompanyFreeMessageDto;
import com.ihr360.oneclick.entity.NotifyStateType;
import com.ihr360.oneclick.modal.SendMessage;
import com.ihr360.oneclick.modal.SendMessageResponse;
import com.ihr360.oneclick.service.SpreadsheetRowService;
import com.ihr360.rest.service.IrenshiDubboProviderService;
import com.ihr360.rest.service.IrenshiWeixinService;
import com.ihr360.rest.service.Ihr360SharedProvideService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;

/**
 * @author tom
 * @date 17-12-28
 */
@Service
public class ExecuteSendTaskServiceImpl implements ExecuteSendTaskService {

    private final static Logger logger = LoggerFactory.getLogger(ExecuteSendTaskServiceImpl.class);

    @Autowired
    private MessageSendTaskDao messageSendTaskDao;
    @Autowired
    private MessageSendRecordDao messageSendRecordDao;
    @Autowired
    private IrenshiWeixinService irenshiWeixinService;
    @Autowired
    private IrenshiDubboProviderService irenshiDubboProviderService;
    @Autowired
    private CompanyFreeMessageDao companyFreeMessageDao;
    @Autowired
    private SpreadsheetRowDao spreadsheetRowDao;
    @Autowired
    private SpreadsheetRowService spreadsheetRowService;
    @Autowired
    private SmsConfig smsConfig;
    @Autowired
    private Ihr360SharedProvideService ihr360SharedProvideService;

    private static int maxCycleNum = 10;


    @Override
    public void execute(String taskId) {
        MessageSendTaskDto messageSendTaskDto = null;
        List<MessageSendRecordDto> messageSendRecordDtoList = null;
        int cycleNum = 0;
        // 事件异步调用会出现任务保存到数据库的时间差，暂使用10次循环获取解决。
        while (cycleNum < maxCycleNum) {
            try {
                logger.debug("第" + cycleNum + "次进入查询任务是否存在");
                messageSendTaskDto = messageSendTaskDao.findOne(taskId);
                messageSendRecordDtoList = messageSendRecordDao.findByTaskId(taskId);
                if (messageSendTaskDto != null && !CollectionUtils.isEmpty(messageSendRecordDtoList)) {
                    break;
                }
                logger.debug("Not getting the message send task, Try to recapture! taskId: {}.", taskId);
                Thread.sleep(1000l);
                cycleNum++;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        if (messageSendTaskDto == null) {
            logger.error("Send the interrupt! Not getting the message send task, taskId: {}", taskId);
            return;
        }
        if (messageSendTaskDto.getDoStatus() != MessageSendTaskDto.DoStatus.DEFAULT) {
            return;
        }

       /* List<SpreadsheetRowDto> spreadsheetRowDtoList = spreadsheetRowDao.findBySpreadsheetId(messageSendTaskDto.getSheetId());
        Map<String, SpreadsheetRowDto> spreadsheetRowDtoMap = spreadsheetRowDtoList.stream().collect(Collectors.toMap(SpreadsheetRowDto::getId, spreadsheetRowDto -> spreadsheetRowDto));*/
        String companyId = messageSendTaskDto.getCompanyId();
        messageSendTaskDto.setDoStatus(MessageSendTaskDto.DoStatus.DOING);
        messageSendTaskDao.save(messageSendTaskDto);
        List<MessageSendRecordDto> sendRecordDtoList = messageSendRecordDao.findByTaskIdAndSendStatus(messageSendTaskDto.getId(),
                MessageSendRecordDto.SendStatus.DEFAULT);
        if (!CollectionUtils.isEmpty(sendRecordDtoList)) {
            switch (messageSendTaskDto.getMessageType()) {
                case MessageSendTaskDto.MessageType.SMS:
                    logger.info("进入短信发送!!!");
                    // 计算短信费用余额
                    CompanyFreeMessageDto companyFreeMessageDto = getCompanyFreeMessage(messageSendTaskDto.getCompanyId());
                    int smsFreeCount = companyFreeMessageDto.getSmsFreeCount();
                    for (MessageSendRecordDto messageSendRecordDto : sendRecordDtoList) {
                        SendMessageResponse res = null;
                        SendMessage sendMessage = new SendMessage();
                        sendMessage.setMobileNo(messageSendRecordDto.getSendId());
                        sendMessage.setMessageTemplate(messageSendRecordDto.getContent());
                        Set<SendMessage> payMessageSet = new HashSet<>();
                        payMessageSet.add(sendMessage);
                        if (smsFreeCount > 0) {
                            res = irenshiDubboProviderService.sendSms(payMessageSet, companyId, messageSendRecordDto.getSpreaadsheetRowId(), true);
                            companyFreeMessageDto.setSmsFreeCount(smsFreeCount--);
                        }else {
                            res = irenshiDubboProviderService.sendSms(payMessageSet, companyId, messageSendRecordDto.getSpreaadsheetRowId(), false);
                        }
                        //SpreadsheetRowDto spreadsheetRowDto = spreadsheetRowDtoMap.get(messageSendRecordDto.getSpreaadsheetRowId());
                        if (res == null || res.getSuccessCount() == 0) {
                            logger.error("invoke pay project send sms error! taskId:" + messageSendTaskDto.getId());
                            messageSendRecordDto.setSendStatus(MessageSendRecordDto.SendStatus.SEND_FAILED);
                            spreadsheetRowService.updateSpreadsheetRowNoticeStatus(messageSendRecordDto.getSpreaadsheetRowId(),NotifyStateType.SEND_FAILURE,1);
                        } else {
                            logger.info(JSONObject.toJSONString(res));
                            spreadsheetRowService.updateSpreadsheetRowNoticeStatus(messageSendRecordDto.getSpreaadsheetRowId(),NotifyStateType.SEND_SUCCESS,1);
                        }
                    }
                    companyFreeMessageDao.save(companyFreeMessageDto);

                    /*// 封装短信参数
                    List<SendMessage> sendMessageList = new ArrayList<>();
                    for (MessageSendRecordDto messageSendRecord : sendRecordDtoList) {
                        SendMessage sendMessage = new SendMessage();
                        sendMessage.setMobileNo(messageSendRecord.getSendId());
                        sendMessage.setMessageTemplate(messageSendRecord.getContent());
                        sendMessageList.add(sendMessage);
                    }


                    Set<SendMessage> payMessageSet = new HashSet<>();
                    Set<SendMessage> freeMessageSet = new HashSet<>();
                    int smsTotalCount = sendMessageList.size();
                    if (smsFreeCount > 0) {
                        if (smsFreeCount >= smsTotalCount) {
                            freeMessageSet.addAll(sendMessageList.subList(0, smsTotalCount));
                        } else {
                            freeMessageSet.addAll(sendMessageList.subList(0, smsFreeCount));
                            payMessageSet.addAll(sendMessageList.subList(smsFreeCount, smsTotalCount));
                        }
                    } else {
                        payMessageSet.addAll(sendMessageList);
                    }
                    if (freeMessageSet.size() > 0) {
                        // 免费发送
                        SendMessageResponse res = irenshiDubboProviderService.sendSms(freeMessageSet, companyId, messageSendTaskDto.getUserId(), true);
                        if (res == null) {
                            logger.error("invoke pay project send sms error! taskId:" + messageSendTaskDto.getId());
                        } else {
                            logger.info(JSONObject.toJSONString(res));
                        }
                        companyFreeMessageDto.setSmsFreeCount(smsFreeCount - freeMessageSet.size());
                        companyFreeMessageDao.save(companyFreeMessageDto);
                    }
                    if (payMessageSet.size() > 0) {
                        // 付费发送
                        SendMessageResponse res = irenshiDubboProviderService.sendSms(payMessageSet, companyId, messageSendTaskDto.getUserId(), false);
                        if (res == null) {
                            logger.error("invoke pay project send sms error! taskId:" + messageSendTaskDto.getId());
                        } else {
                            logger.info(JSONObject.toJSONString(res));
                        }
                    }*/
                    break;
                case MessageSendTaskDto.MessageType.WEICHAT:
                    logger.info("进入微信发送");
                    sendRecordDtoList.forEach(sendRecordDto -> {
                        WxMpTemplateMessage wxMpTemplateMessage = new WxMpTemplateMessage();
                        List<WxMpTemplateData> wxMpTemplateDataList = JSONArray.parseArray(sendRecordDto.getPlaceholderValues(), WxMpTemplateData.class);
                        wxMpTemplateMessage.setToUser(sendRecordDto.getSendId());
                        wxMpTemplateMessage.setTemplateId(sendRecordDto.getVendorTemplateId());
                        wxMpTemplateMessage.setDatas(wxMpTemplateDataList);
                        //TODO: 保存发送后状态
                        boolean result = irenshiWeixinService.templateMsgSendSignle(wxMpTemplateMessage);
                        //SpreadsheetRowDto spreadsheetRowDto = spreadsheetRowDtoMap.get(sendRecordDto.getSpreaadsheetRowId());
                        if (result) {
                            spreadsheetRowService.updateSpreadsheetRowNoticeStatus(sendRecordDto.getSpreaadsheetRowId(),NotifyStateType.SEND_SUCCESS,2);
                        }else {
                            sendRecordDto.setSendStatus(MessageSendRecordDto.SendStatus.SEND_FAILED);
                            spreadsheetRowService.updateSpreadsheetRowNoticeStatus(sendRecordDto.getSpreaadsheetRowId(),NotifyStateType.SEND_FAILURE,2);
                        }
                    });
                    break;
                case MessageSendTaskDto.MessageType.PROGRAM:
                	// TODO: 小程序发送消息通知,由于由7天form_id限制, 暂时不启用
                    List<WxMpProgramTemplateMessage> programMessageList = new ArrayList<>();
                    sendRecordDtoList.forEach(sendRecordDto -> {
                        WxMpProgramTemplateMessage wxMpTemplateMessage = new WxMpProgramTemplateMessage();
                        List<WxMpTemplateData> wxMpTemplateDataList = JSONArray.parseArray(sendRecordDto.getPlaceholderValues(), WxMpTemplateData.class);
                        wxMpTemplateMessage.setToUser(sendRecordDto.getSendId());
                        wxMpTemplateMessage.setTemplateId(sendRecordDto.getVendorTemplateId());
                        wxMpTemplateMessage.setDatas(wxMpTemplateDataList);
                        wxMpTemplateMessage.setFormId(UUID.randomUUID().toString());
                        programMessageList.add(wxMpTemplateMessage);
                    });
                    irenshiWeixinService.programTemplateMsgSendBatch(programMessageList);
                case MessageSendTaskDto.MessageType.EMAIL:
                    logger.info("进入邮件发送!!!");
                    sendRecordDtoList.forEach(sendRecordDto -> {
                        sendRecordDto.getSendId();
                        boolean result = false;
                        try {
                            MailRequest mailRequest = new MailRequest();
                            mailRequest.setCompanyId(companyId);
                            mailRequest.setRecipient(sendRecordDto.getSendId());
                            mailRequest.setEmailContent(sendRecordDto.getContent());
                            mailRequest.setSubject("您的工资条");
                            result = ihr360SharedProvideService.sendMail(mailRequest);
                        } catch (Exception e){
                            logger.error("邮件发送失败",e.getMessage());
                            sendRecordDto.setFailedReason(e.getMessage());
                            sendRecordDto.setSendStatus(MessageSendRecordDto.SendStatus.SEND_FAILED);
                        }
                        //SpreadsheetRowDto spreadsheetRowDto = spreadsheetRowDtoMap.get(sendRecordDto.getSpreaadsheetRowId());
                        if (result) {
                            spreadsheetRowService.updateSpreadsheetRowNoticeStatus(sendRecordDto.getSpreaadsheetRowId(),NotifyStateType.SEND_SUCCESS,3);
                        } else {
                            sendRecordDto.setSendStatus(MessageSendRecordDto.SendStatus.SEND_FAILED);
                            spreadsheetRowService.updateSpreadsheetRowNoticeStatus(sendRecordDto.getSpreaadsheetRowId(),NotifyStateType.SEND_FAILURE,3);
                        }
                    });
                    break;
                default:
                    logger.error("Unknown message type!");
                    break;
            }
            //spreadsheetRowDao.save(spreadsheetRowDtoList);
            messageSendRecordDao.save(sendRecordDtoList);
        }
        messageSendTaskDto.setDoStatus(MessageSendTaskDto.DoStatus.FINISHED);
        messageSendTaskDao.save(messageSendTaskDto);
    }

    private synchronized CompanyFreeMessageDto getCompanyFreeMessage(String companyId) {
        CompanyFreeMessageDto companyFreeMessageDto = companyFreeMessageDao.findByCompanyId(companyId);
        if (companyFreeMessageDto == null) {
            companyFreeMessageDto = new CompanyFreeMessageDto();
            companyFreeMessageDto.setCompanyId(companyId);
            companyFreeMessageDto.setSmsFreeCount(smsConfig.getFreeSmsCount());
            companyFreeMessageDao.save(companyFreeMessageDto);
        }
        return companyFreeMessageDto;
    }


}
